﻿#include "mytcpserver.h"

#include <QTcpSocket>
#include <QDebug>
#include <QDir>
#include <QApplication>
#include "main.h"
//单个包数据大小
#define PKG_DATA_SIZE  1024

MyTcpServer::MyTcpServer(QObject *parent) :
    QTcpServer(parent)
{
    qDebug()<<__FUNCTION__;
    //花样文件目录
    QDir apppath(qApp->applicationDirPath());
    QString filePath = apppath.path() + QDir::separator() + PATTERNPATH;
    m_firstFilePath = QDir(filePath).absolutePath();//为了将"\"变为"/"
    m_socket = new QTcpSocket();
    reflashFileTrans();
}

MyTcpServer::~MyTcpServer()
{
    delete m_socket ;
    qDebug()<<__FUNCTION__;
}

/**
 * @brief 数据打包
 * @param cmd1
 * @param cmd2
 * @param data
 * @return
 */
QByteArray MyTcpServer::createDataPacket(int cmd1, int cmd2, QByteArray data)
{
    QByteArray cmd;
    cmd += cmd1;
    cmd += cmd2;
    QByteArray bytes(sizeof(FilePkgHead),0);
    FilePkgHead head;
    memcpy(&head.cmd,cmd.data(),sizeof(short int));
    head.dataSize = data.size();
//    qDebug()<<"data.size:"<<data.size();
//    qDebug()<<"FilePkgHead.size:"<<sizeof(FilePkgHead);
    memcpy(bytes.data(),&head,sizeof(FilePkgHead));
    bytes+=data;
    return bytes;
}

void MyTcpServer::reflashFileTrans()
{
    totalBytes = 0;
    m_fileBuffer_Recv.clear();
    m_fileBuffer_Send.clear();
//    fileName.clear();
}

#ifdef Q_OS_WIN
void MyTcpServer::incomingConnection(qintptr socketDescriptor)
#endif
#ifdef Q_OS_LINUX
void MyTcpServer::incomingConnection(int socketDescriptor)
#endif
{
    // 当有客户端连接时，会调用这个方法
        qDebug()<<"MyTcpServer::incomingConnectio";

        // 设置socket的描述符
        m_socket->setSocketDescriptor(socketDescriptor);

        // 连接信号和槽来读取来自客户端的数据和处理断开连接
        connect(m_socket, SIGNAL(readyRead()), this, SLOT(connectionHandle()));
        connect(m_socket,  SIGNAL(disconnected()), this, SLOT(disconnectHandle()));
}

void MyTcpServer::connectionHandle()
{
    QByteArray buffer = m_socket->readAll();

    if(!buffer.isEmpty())
    {
        char cmd1 = buffer.at(0);
        Q_UNUSED(cmd1)
        char cmd2 = buffer.at(1);
        FilePkgHead *head = (FilePkgHead *)buffer.data();
        QByteArray data =  buffer.right(head->dataSize);

        qDebug()<<"=============================================================================";
        qDebug()<< "dataLength:" <<head->dataSize<<" ";


        switch (cmd2)
        {
        case 0x01://保存文件名和文件大小
        {
            if(totalBytes !=0)
                qWarning()<<"0x01>>(totalBytes !=0)";

            reflashFileTrans();

            //记录文件名称和文件大小
            memcpy(&totalBytes,data.data(),sizeof(qint64));
            const qint64 memory_10M = 10*1024*1024;
            if(totalBytes > memory_10M) //文件大小超过10m
            {
                m_socket->write(createDataPacket(0x01,0x05,NULL));
                reflashFileTrans();
                return;
            }

            data = data.right(data.size() - sizeof(qint64));
            fileName = QString::fromUtf8(data);
            fileName = m_firstFilePath + QDir::separator() + fileName;

            qDebug()<<"0x01>>Recv Path Name:" << fileName;
            qDebug()<<"0x01>>Recv File Name:" << fileName;
            qDebug()<<"0x01>>Recv File TotalBytes:" << totalBytes;

            if(QFile(fileName).exists())//文件存在，取消传输
            {
                m_socket->write(createDataPacket(0x01,0x05,NULL));
                reflashFileTrans();
                qDebug()<<fileName<<"QFile(fileName).exists()xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
            }

            //刷新缓冲区
            m_fileBuffer_Recv.reserve(totalBytes);
            m_fileBuffer_Recv.resize(0);

            m_socket->write(createDataPacket(0x01,0x04,NULL));
            m_socket->flush();
            break;
        }

        case 0x02://接收文件数据
        {
            if((totalBytes == 0) || (totalBytes <= m_fileBuffer_Recv.size()))
            {
                qWarning()<< "0x02>>(totalBytes == 0) || (totalBytes <= m_fileBuffer_Recv.size())";
                qWarning()<< "0x02>>totalBytes:"<<totalBytes<<"m_fileBuffer_Recv.size():"<<m_fileBuffer_Recv.size();
                reflashFileTrans();
                return;
            }

            m_fileBuffer_Recv += data;//缓冲数据
            m_socket->write(createDataPacket(0x01,0x04,NULL));
            m_socket->flush();
            break;
        }

        case 0x03://接收文件完成
        {
            if(m_fileBuffer_Recv.size() == totalBytes)
            {
                QFile file(fileName);
                if(!file.open(QFile::WriteOnly))
                {
                    qWarning() << "0x03 open file error!";
                    return;
                }else{
                    file.write(m_fileBuffer_Recv);
                    file.close();
                    qDebug() << "0x03 file.trans success>>>"<<fileName;;
                }
            }
            else
                qWarning()<< "0x03>>(m_fileBuffer_Recv.size() != totalBytes)";

            reflashFileTrans();
            break;
        }

        case 0x04://发送文件数据
        {
            if(!m_fileBuffer_Send.isEmpty())
            {
                QByteArray outBlock = m_fileBuffer_Send.left(qMin(m_fileBuffer_Send.size(),PKG_DATA_SIZE));
                m_fileBuffer_Send =  m_fileBuffer_Send.right(m_fileBuffer_Send.size() - outBlock.size());//保留后一部分
                QByteArray packet = createDataPacket(0x01,0x02,outBlock);
                m_socket->write(packet);
                m_socket->flush();
            }
            else
            {
                qDebug()<<"0x04>>m_fileBuffer_Send.isEmpty()"<<m_fileBuffer_Send.size();
                QByteArray packet = createDataPacket(0x01,0x03,"File Trans Close");
                m_socket->write(packet);
                m_socket->flush();
                reflashFileTrans();
            }
            break;
        }

        case 0x05://取消传输
        {
            reflashFileTrans();
            qDebug()<<"0x05"<<data;
        }

        default:
            break;
        }
    }
}

void MyTcpServer::disconnectHandle()
{
    reflashFileTrans();
    disconnect(m_socket, SIGNAL(readyRead()), this, SLOT(connectionHandle()));
    disconnect(m_socket,  SIGNAL(disconnected()), this, SLOT(disconnectHandle()));

    qDebug()<<"MyTcpServer disconnection";
}
